############################################################################
#
# DIM - A Direct Interaction Manager for SAGE
# Copyright (C) 2007 Electronic Visualization Laboratory,
# University of Illinois at Chicago
#
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
#  * Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaim`er.
#  * Redistributions in binary form must reproduce the above
#    copyright notice, this list of conditions and the following disclaimer
#    in the documentation and/or other materials provided with the distribution.
#  * Neither the name of the University of Illinois at Chicago nor
#    the names of its contributors may be used to endorse or promote
#    products derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# Direct questions, comments etc about SAGE UI to www.evl.uic.edu/cavern/forum
#
# Author: Ratko Jagodic
#
############################################################################


import overlays.splitter as splitterMod
#import overlays.menu as menu
import overlays.button as button
import overlays.thumbnail as thumbnail
import overlays.label as label
import overlays.sizer as sizer
import overlays.panel as panel
from globals import *
import pickle
import time
import operator
import subprocess as sp
from sageGate import addGate, getGate
from eventHandler import EventHandler
from ui.spaceManager import *

sys.path.append("../dim/hwcapture")
from managerConn import ManagerConnection

def makeNew():
    """ this is how we instantiate the object from
    the main program that loads this plugin """
    return Sections()


# must have this to load the plugin automatically
TYPE = UI_PLUGIN
LOAD_LAST = True  # loads the plugin last because it depends on others


# how many minimize sections do we make?
# the more we have, the closer the app will be
# to its original position when minimized...
NUM_MINIMIZE_SECTIONS = 1



class Section:
    def __init__(self, bounds, parent, relPos=None, makeWidgets=True, tiled=False, type=NOT_DEFINED_TYPE):
        self.addWidget = getOverlayMgr().addWidget
        self.removeWidget = getOverlayMgr().removeWidget
        self.org = getLayoutOrganization()
        self.sageData = getSageData()

        self.relPos = relPos
        self.splitter = None
        self.bounds = bounds
        self.children = []  # only two, left and right
        self.parent = parent
        self._isMinimizePanel = False
        self._collapsed = False

        # min distance we have to drag to minimize all or collapse a section... in pixels
        self.localdisplay = self.sageData.getDisplayInfo()
        self.__minGestureDist = int(0.12 * min(self.localdisplay.sageW, self.localdisplay.sageH))

        # controlled by Organization ui
        self.tiled = tiled
        self.tightFlag = False

        # is it a shared section
        self.isShared = False
        self.hostip = None
        # shared pointers info
        self.manager = None
        self.pointers = set()
        self.remotedisplay = None

        # hyejung
        self.spaceManager = DynamicSpaceManager(self, bounds)
        self.windowsById = []
        self.loaded_time  =  time.time()
        self.max_priority = 1
        self.tileW =0
        self.tileH =0
        self.areaW =0
        self.areaH =0
        self.numCols = 0
        self.numRows = 0
        self.__tiledWindows =[]
        self.appWindows = {}
        self.newpos_config = 1
        self.appCounter = 1
        self.userPriorityScale = 1.0
        self.userDistributedScale = 1.0
        self.inSec = None
        self.inType = type
        self.outSec = None
        self.dynamicMode = 3
        self.agentMode = False
        self.vs_x = 0
        self.vs_y = 0

        # widgets dont have to be made if we are loading this section
        # from a saved state where this section had children
        self.p = None
        if makeWidgets:
            self.makeWidgets()
        if self.parent == None :
            writeLog(LOG_SECTION_NEW, self, self.bounds, 3)
        else :
            writeLog(LOG_SECTION_NEW, self, self.bounds,self.parent.splitter.direction)
        self.loaded_time  =  time.time()
        self.max_priority = 1

        # userinfo index - added by sanghwa
        self.sectionLock = False # Lock flag - added by sanghwa
        self.userinfoP = None
        self.dataInInfoP = None
        self.dataInUser = []
        self.userIdx_dataIn = 0

    def setIn(self, type, insec=None):
        self.inSec = insec
        #self.inType = type
        self.setDataIn(type)

    def setOut(self, out):
        if out :
            self.inType = SECTION_TYPE
            getLayoutSections().setFlow()
            self.outSec = out

    def transfer(self, moveobj):
        app = None
        if self.outSec != None :
            # transfer windows... into other
            if self.tiled == True :
                #print self.windowsById
		if len(self.windowsById) > 0 :
                    app_id = self.windowsById[0]
                    all_windows = self.sageData.getRunningApps().values()
                    for w in all_windows:
                        if app_id == w.getId() :
                            app = w
                            break
                    if app :
                        app.section = self.outSec
                    self.windowsById.remove(app_id)
            else :
                windows = []
                all_windows = self.sageData.getRunningApps().values()
                for w in all_windows:
                    if w.section == self:
                        windows.append(w)
                app_id = self.spaceManager.runSort(windows, moveobj)
		if app_id >= 0 :
                    for w in all_windows:
                        if app_id == w.getId() :
                            app = w
                            break
                    if app :
                        app.section = self.outSec
            self.outSec.transfer(app)

        # for proper pickling...
    def __getstate__(self):
        d = {}
        d['bounds'] = self.bounds
        d['parent'] = self.parent
        d['relPos'] = self.relPos
        d['tiled'] = self.tiled
        d['children'] = self.children
        d['splitter'] = self.splitter
        d['_collapsed'] = self._collapsed
        return d

    def makeWidgets(self):
        self._makePanel()

        self.mainSizer = sizer.Sizer(direction=VERTICAL)
        self.mainSizer.align(CENTER, BOTTOM)

        self.subSizer = sizer.Sizer(direction=HORIZONTAL)
        self.subSizer.align(LEFT, TOP)

        self.s1 = sizer.Sizer(direction=VERTICAL)
        self.s1.align(LEFT, BOTTOM)

        bs = 60
        alpha = 120

	# clear button - added by GD, modified by HJ
        #btnWidth = int(bs*1.5)
        btnWidth = int(bs*3)
        self.clear = thumbnail.makeNew()
        self.clear.align(CENTER, CENTER, xMargin=20, yMargin=10)
        #self.clear.setToggle(True)
        self.clear.setLabel("Clear", fontSize=NORMAL)
        self.clear.alignLabel(CENTER)
        self.clear.setSize(btnWidth, bs)
	self.clear.onUp(self.__onClearBtn)
        self.clear.setTransparency(alpha)


        # layout btn
        self.layoutB = self.org.makeLayoutButtons(bs, alpha)
        self.layoutB.setUserData(self)
        if self.tiled:
            self.layoutB.setState(BUTTON_DOWN)
        self.s1.addChild(self.layoutB)

        # splitter buttons
        self.vb = thumbnail.Thumbnail()
        self.vb.setSize(bs,bs)
        self.vb.setUpImage(opj("images", "vertical_divider_btn_up.png"))
        self.vb.setDownImage(opj("images", "vertical_divider_btn_over.png"))
        self.vb.setOverImage(opj("images", "vertical_divider_btn_over.png"))
        self.vb.align(CENTER, CENTER, xMargin=10, yMargin=10)
        self.vb.setUserData(VERTICAL)
        self.vb.setScaleMultiplier(2.0)
        self.vb.onUp(self.__onSplitBtn)
        self.s1.addChild(self.vb)

        self.subSizer.addChild(self.s1)

        self.s2 = sizer.Sizer(direction=VERTICAL)
        self.s2.align(LEFT, BOTTOM)
        self.s2.addChild(self.clear)
	# new
        self.clearall = thumbnail.makeNew()
        self.clearall.align(CENTER, CENTER, xMargin=20, yMargin=10)
        self.clearall.setLabel("New", fontSize=NORMAL)
        self.clearall.alignLabel(CENTER)
        self.clearall.setSize(btnWidth, bs)
	self.clearall.onUp(self.__onNewBtn)
        self.clearall.setTransparency(alpha)
        self.s2.addChild(self.clearall)

	'''# all action button - test
        self.prev = thumbnail.makeNew()
        self.prev.align(CENTER, CENTER, xMargin=20, yMargin=10)
        self.prev.setLabel("Apply", fontSize=NORMAL)
        self.prev.alignLabel(CENTER)
        self.prev.setSize(btnWidth, bs)
	self.prev.onUp(self.__onTestBtn)
        self.prev.setTransparency(alpha)
        self.s2.addChild(self.prev)'''



        # splitter buttons
        self.hb = thumbnail.Thumbnail()
        self.hb.setSize(bs,bs)
        self.hb.align(CENTER, CENTER, xMargin=10, yMargin=10)
        self.hb.setUpImage(opj("images", "horizontal_divider_btn_up.png"))
        self.hb.setDownImage(opj("images", "horizontal_divider_btn_over.png"))
        self.hb.setOverImage(opj("images", "horizontal_divider_btn_over.png"))
        self.hb.setUserData(HORIZONTAL)
        self.hb.setScaleMultiplier(2.0)
        self.hb.onUp(self.__onSplitBtn)
        self.s1.addChild(self.hb)

        

        self.s3 = sizer.Sizer(direction=VERTICAL)
        self.s3.align(LEFT, BOTTOM)
        btnWidth = int(bs*3)
        self.vs = thumbnail.Thumbnail()
        self.vs.setSize(bs,bs)
        self.vs.align(CENTER, CENTER, xMargin=20, yMargin=10)
        self.vs.setLabel("Browser", fontSize=NORMAL)
        self.vs.alignLabel(CENTER)
        self.vs.setSize(btnWidth, bs)
        self.vs.onUp(self.__onBrowserBtn)
        self.vs.setTransparency(alpha)
        self.s3.addChild(self.vs)

        self.di = thumbnail.Thumbnail()
        self.di.setSize(bs,bs)
        self.di.align(CENTER, CENTER, xMargin=20, yMargin=10)
        self.di.setLabel("Set In", fontSize=NORMAL)
        self.di.alignLabel(CENTER)
        self.di.setSize(btnWidth, bs)
        self.di.onUp(self.__onDataInBtn)
        self.di.setTransparency(alpha)
        self.s3.addChild(self.di)

        '''self.sc = thumbnail.Thumbnail()
        self.sc.setSize(bs,bs)
        self.sc.align(CENTER, CENTER, xMargin=20, yMargin=10)
        self.sc.setLabel("Set Center", fontSize=NORMAL)
        self.sc.alignLabel(CENTER)
        self.sc.setSize(btnWidth, bs)
        self.sc.onUp(self.__onSetCenterBtn)
        self.sc.setTransparency(alpha)
        self.s3.addChild(self.sc)'''


        self.subSizer.addChild(self.s2)
        self.subSizer.addChild(self.s3)

        self.mainSizer.addChild(self.subSizer)

        btnWidth = int(bs*1.5)

	# show menu or not
        #self.s.toggleVisible()

        # i.e. this isn't root section...
        if self.parent:
            # collapse button
            '''
            self.collapseBtn = thumbnail.Thumbnail()
            self.collapseBtn.setSize(bs,bs)
            self.collapseBtn.setToggle(True)
            self.collapseBtn.align(CENTER, CENTER, xMargin=10, yMargin=10)
            self.collapseBtn.setUpImage(opj("images", "fast-forward.png"))
            self.collapseBtn.setDownImage(opj("images", "rewind.png"))
            self.collapseBtn.setScaleMultiplier(2.0)
            self.collapseBtn.onUp(self.__onCollapseBtn)
            self.collapseBtn.onDown(self.__onCollapseBtn)
            self.collapseBtn.setTransparency(alpha)
            #self.s.addChild(self.collapseBtn)
            '''

            # close button
            closeB = thumbnail.makeNew()
            closeB.setSize(bs,bs)
            closeB.setUpImage(opj("images", "close_up.png"))
            closeB.setDownImage(opj("images", "close_over.png"))
            closeB.setOverImage(opj("images", "close_over.png"))
            closeB.align(CENTER, CENTER, xMargin=10, yMargin=10)
            closeB.onUp(self.__onRemoveSection)
            closeB.setScaleMultiplier(2.0)
            closeB.setTransparency(alpha)
            self.mainSizer.addChild(closeB)

        self.mp.addChild(self.mainSizer)
        self.p.addChild(self.mp)

        #self.p.addChild(self.s)

        # information
        self.info = sizer.makeNew(direction=VERTICAL)
	self.info2 = sizer.makeNew(direction=HORIZONTAL)
        self.info.align(LEFT, TOP)
        self.labelinfo = None
        if self.tiled:
            if self.dynamicMode == 0 :
                self.labelinfo = label.makeNew(label="Tile Mode", fontSize=LARGER)
            else : # 1
                self.labelinfo = label.makeNew(label="Tile Mode-Display", fontSize=LARGER)
        else :
            if self.dynamicMode == 2 :
                self.labelinfo = label.makeNew(label="Free Mode", fontSize=LARGER)
            elif self.dynamicMode == 3 :
                self.labelinfo = label.makeNew(label="Dynamic Mode", fontSize=LARGER)

        #l.align(CENTER, CENTER)
        self.labelinfo.drawBackground(True)
        if self.tiled:
            self.labelinfo.setBackgroundColor(10,50,50)
        else :
            self.labelinfo.setBackgroundColor(50,50,50)
        # hyejung
        self.labelinfo.setTransparency(150)
        self.info.addChild(self.labelinfo)

        self.inputinfo = None
        # hyejung
        if self.inType == USERINPUT_TYPE:
            self.inputinfo = label.makeNew(label="Data In", fontSize=LARGER)
        elif self.inType == SECTION_TYPE:
            self.inputinfo = label.makeNew(label="Section In", fontSize=LARGER)
        else : # NOT_DEFINED_TYPE
            self.inputinfo = label.makeNew(label="-", fontSize=LARGER)
        self.inputinfo.registerForEvent(EVT_CLICK, self.__onDataInInfo)
        self.inputinfo.drawBackground(True)
        if self.inType == USERINPUT_TYPE:
            self.inputinfo.setBackgroundColor(200,0,0)
        elif self.inType == SECTION_TYPE:
            self.inputinfo.setBackgroundColor(50,10,50)
        else :
            self.inputinfo.setBackgroundColor(50,50,50)
        self.inputinfo.setTransparency(150)
        self.info2.addChild(self.inputinfo)


	#2.Users - added by Sanghwa
        self.userinfo = None
        self.numUsers = 0
	self.userinfo = label.makeNew(label=str(self.numUsers), fontSize=LARGER)
        self.userinfo.registerForEvent(EVT_CLICK, self.__onUserInfo)
	self.userinfo.drawBackground(True)
	self.info2.addChild(self.userinfo)
	self.info.addChild(self.info2)
        self.p.addChild(self.info)

        # hide... other widget.. move to popup
        self.mp.hide()

        self.addWidget(self.p)

    def _setButtonCollapsed(self):
        """ used on reload of state to set the button properly """
        if self._collapsed and self.parent:
            self.collapseBtn.setState(BUTTON_DOWN)
            self.layoutB.hide()


    def _makePanel(self):
        self.p = panel.Panel()
        self.p.setTransparency(1)
        #self.p.setBackgroundColor(255,255,255)
        self.p._canScale = False
        self.p._eventTransparent = True
        #self.p.z = BOTTOM_Z-5
        self.p.fitInWidth(False)
        self.p.fitInHeight(False)
        self._updateSectionBounds()

        self.mp = panel.Panel()
        #self.mp.fitInWidth(False)
        #self.mp.fitInHeight(False)
        self.mp.setPos(self.bounds.left, self.bounds.bottom)
        self.mp.setSize(450, 400)
        self.mp._canScale = False
        self.mp._refresh()


    def hideWidgets(self):
        if self.mp:
            self.mp.hide()


    def showWidgets(self, x, y):
        if self.mp:
            self.vs_x = x
            self.vs_y = y
            # cyber-commons: -320, -70, -230
            y = y-350
	    if len(getLayoutSections().root.children) == 0 :
                y = y+50
            self.mp.setPos(x-60, y)

            self.mp._refresh()
            #print x, y
            self.mp.show()


    def __onRemoveSection(self, btn):
        getLayoutSections().removeSection(self)
        '''if self.inType == USERINPUT_TYPE:
            getLayoutSections().updateInSec()'''


    def removeWidgets(self):
        writeLog(LOG_SECTION_REMOVE, self)
        self.removeWidget(self.p)


    def _updateSectionBounds(self):
        """ updates the widgets inside because the position and/or size changed """

        if self.p:
            self.p.setPos(self.bounds.left, self.bounds.bottom)
            self.p.setSize(self.bounds.getWidth(), self.bounds.getHeight())
            self.p._refresh()
        self.spaceManager.updateBound(self.bounds)
        if self.tiled == False :
            self.createSpace(None)



    def _updateSplitter(self):
        """ update the position and size of the splitter if the section it splits changed """

        if self.splitter:
            if self.splitter.direction == HORIZONTAL:
                x = self.bounds.left
                y = self.bounds.bottom + int(round(self.bounds.getHeight() * self.splitter.relPos))
                w = self.bounds.getWidth()
                h = self.splitter.getHeight()
            else:
                y = self.bounds.bottom
                x = self.bounds.left + int(round(self.bounds.getWidth() * self.splitter.relPos))
                w = self.splitter.getWidth()
                h = self.bounds.getHeight()
            self.splitter.setPos(x,y)
            self.splitter.setSize(w,h)
            self.splitter._refresh()


        # is x,y inside the section?
    def isIn(self, x, y):
        return self.bounds.isIn(x,y)


        # returns all apps that are in this section
    def getSectionApps(self):
        a = []
        for app in self.sageData.getRunningApps().values():
            if app.section == self:
                a.append(app)
        return a

    def createSpace(self, app):
        if app != None :
            app.section = self
        if self.dynamicMode < 2 :
            return
        elif self.dynamicMode == 2 and app :
            self.spaceManager.createFullRectangle(app)
            return

        # ------------------------------
        # DYNAMIC
        # get window list in this section
        # question??? why??? we need this way...
        app_sortedWindows = []
        app_staticWindows = []
        windows = self.sageData.getRunningApps().values()
        for w in windows :
            if w.section == self:
                if w.fixed == True :
                    app_staticWindows.append(w)
                else :
                    added = False
                    index = 0
                    for S in app_sortedWindows :
                        if S.priority > w.priority :
                            app_sortedWindows.insert(index,w)
                            added = True
                            break
                        index += 1
                    if added == False :
                        app_sortedWindows.append(w)

        # clear space
        self.spaceManager.clearRectangles()

        # static windows goes first
        for w in app_staticWindows:
            self.spaceManager.createStaticRectangle(w)

        # find min and max
        numWindows =  len(app_sortedWindows)
        if numWindows > 0 :
            w = app_sortedWindows[0]
            min_priority = w.priority -1

            # total priority with adjustment
            total_priority = 0
            for w in app_sortedWindows:
                total_priority += (w.priority - min_priority)
            #print "[DEBUG] total = " + str(total_priority)  + " min=" + str(min_priority) + " max=" + str(self.max_priority)

            shared_area = (1.0 - self.userPriorityScale) / (len(app_sortedWindows) * 1.0)
            #print "share area ===> " + str(shared_area)
            for w in app_sortedWindows:
                w.calSizeDesire(min_priority, total_priority, self.userPriorityScale, shared_area)

            app_sortedWindows.reverse()
            w = app_sortedWindows[0]
            self.max_priority = w.priority
            self.appCounter = w.priority +1
            for w in app_sortedWindows:
                self.spaceManager.adjustFullRectangle(w, numApp=numWindows)

            # check empty space
            awidth, aheight = self.spaceManager.checkAvailableSpace()
            #print "awidth -- > ", awidth, aheight
            checkFailed = False
            off = getLayoutSections().off_center - int((self.bounds.right - self.bounds.left)/2.0)

            for w in app_sortedWindows:
	        left = w.left + awidth + off
	        right = left + (w.right - w.left)
                if left <  self.bounds.left :
                    checkFailed = True
                    break
                elif right > self.bounds.right :
                    checkFailed = True
                    break

            if checkFailed == False :
                awidth += off


            for w in app_sortedWindows:
                w.resizeWindow(w.left+awidth, w.right + awidth, w.bottom+aheight, w.top+aheight)

        del app_sortedWindows
        del app_staticWindows
        # ------------------------------ END of DYNAMIC

    def addSpace(self, app):
        self.spaceManager.addRectangle(app)

    def updateSpace(self, app):
        self.spaceManager.updateFullRectangle(app)

    def updatePriority(self, app):
        #  sorting needs to be changed
        app_sortedWindows = []
        app_staticWindows = []
        windows = self.sageData.getRunningApps().values()
        for w in windows :
            if w.section == self:
                if w.fixed == True :
                    app_staticWindows.append(w)
                else :
                    added = False
                    index = 0
                    for S in app_sortedWindows :
                        if S.priority > w.priority :
                            app_sortedWindows.insert(index,w)
                            added = True
                            break
                        index += 1
                    if added == False :
                        app_sortedWindows.append(w)

        # clear space
        self.spaceManager.clearRectangles()

        # static windows goes first
        for w in app_staticWindows:
            self.spaceManager.createStaticRectangle(w)

        # find min and max
        if len(app_sortedWindows) > 0 :
            w = app_sortedWindows[0]
            min_priority = w.priority -1

            # total priority with adjustment
            total_priority = 0
            for w in app_sortedWindows:
                total_priority += (w.priority - min_priority)
            #print "[DEBUG] total = " + str(total_priority)  + " min = " + str(min_priority)

            shared_area = (1.0 - self.userPriorityScale) / (len(app_sortedWindows) * 1.0)
            #print "share area ===> " + str(shared_area)
            for w in app_sortedWindows:
                w.calSizeDesire(min_priority, total_priority, self.userPriorityScale, shared_area)

            app_sortedWindows.reverse()
            w = app_sortedWindows[0]
            self.appCounter = w.priority +1
            current = False
            for w in app_sortedWindows:
                if w.priority > app.priority :
                    # app.resizeWindow(w.agent.left, w.agent.right, w.agent.bottom, w.agent.top)
                    self.spaceManager.createStaticRectangle(w)
                elif w.priority == app.priority :
                    if w == app :
                        self.spaceManager.createAgentRectangle(w)
                    elif w.agent.settlement == 1 :
                        self.spaceManager.createStaticRectangle(w)
                else :
                    if w.agent.settlement == 1 :
                        self.spaceManager.createStaticRectangle(w)

            # INEFFICIENT
	    numWindows = len(app_sortedWindows)
            for w in app_sortedWindows:
                if w.priority <= app.priority :
                    if w.agent.settlement == 0 :
                        self.spaceManager.adjustFullRectangle(w, numApp=numWindows)

        del app_sortedWindows
        del app_staticWindows


    def releaseSpace(self, app):
        if self.dynamicMode < 2 :
            return
        elif self.dynamicMode == 2 :
            self.spaceManager.deleteFullRectangle(app)
            # reset
            self.appCounter = 1
            return
        elif self.dynamicMode == 3 :
            self.spaceManager.deleteFullRectangle(app)

        # ------------------------------
        # DYNAMIC
        # get window list in this section
        # question??? why??? we need this way...
        app_sortedWindows = []
        app_staticWindows = []
        windows = self.sageData.getRunningApps().values()
        for w in windows :
            if app.sailID == w.sailID :
                continue
            if w.section == self:
                if w.fixed == True :
                    app_staticWindows.append(w)
                else :
                    added = False
                    index = 0
                    for S in app_sortedWindows :
                        if S.priority > w.priority :
                            app_sortedWindows.insert(index,w)
                            added = True
                            break
                        index += 1
                    if added == False :
                        app_sortedWindows.append(w)

        # clear space
        self.spaceManager.clearRectangles()

        # static windows goes first
        for w in app_staticWindows:
            self.spaceManager.createStaticRectangle(w)

        app_count = len(app_sortedWindows)
        if app_count > 0 :
            # find min and max
            w = app_sortedWindows[0]
            min_priority = w.priority -1

            # total priority with adjustment
            total_priority = 0
            for w in app_sortedWindows:
                total_priority += (w.priority - min_priority)
            #print "[DEBUG] total = " + str(total_priority)  + " min = " + str(min_priority)

            if total_priority == 0 :
                shared_area = 1.0 / app_count
                for w in app_sortedWindows:
                    w.setSizeDesire(ity, total_priority, self.userPriorityScale, shared_area)
            else :
                shared_area = (1.0 - self.userPriorityScale) / (app_count * 1.0)
                #print "share area ===> " + str(shared_area)
                for w in app_sortedWindows:
                    w.calSizeDesire(min_priority, total_priority, self.userPriorityScale, shared_area)

            app_sortedWindows.reverse()
            w = app_sortedWindows[0]
            self.appCounter = w.priority +1
            for w in app_sortedWindows:
                self.spaceManager.adjustFullRectangle(w, numApp=app_count)
        else :
            self.appCounter = 1
        del app_sortedWindows
        del app_staticWindows


    def fitAppInSection(self, app, cx=None, cy=None):

        # first check if the windows were tiled in the old section
        # if so, re-tile it because we just removed an app from there
        prevSec = app.section
        app.section = self

        # if this is a minimize panel, mark the app as minimized
        appOverlay = getOverlayMgr().getAppOverlay(app)
        if appOverlay:
            appOverlay.minimize( self._isMinimizePanel )
        else:
            # at least set this... then the appOverlay will set it once it initializes
            app.minimize( self._isMinimizePanel )


        # if the section is not shared and the app is shared, kill it remotely
        if not self.isShared and app.isShared:
            local_apps = getSageGate().getAppStatus()
            local_params = local_apps[str(app.appId)][1].split()
            directory, local_filename = os.path.split( local_params[-1] )
            for h in app.sharedHosts:
                rgate, rdata = getGate( h )
                # Get local information
                remote_apps  = rgate.getAppStatus()
                running_apps = rdata.getRunningApps()
                winner = None
                for k in remote_apps:
                    ra = remote_apps[k]
                    rparams = ra[1].split()
                    rdir, rfile = os.path.split( rparams[-1] )
                    if rfile == local_filename:
                        winner = int(k)
                for v in running_apps.values():
                    remote_filename = v.title
                    if v.appName == app.appName:
                        if v.appId == winner:
                            rgate.sendAppEvent(APP_QUIT, v.sailID)
            app.isShared = False
            app.sharedHosts.clear()
        else:
            # if the section is shared and not the app, share it then
            if self.isShared and not app.isShared:
                if "imageviewer" in app.getName().lower() or "mplayer" in app.getName().lower() or "pdfviewer" in app.getName().lower():
                    gate = getSageGate()
                    addGate(self.hostip)
                    gate.showContentRemotely(app, self.hostip)
                    app.sharedHosts.add(self.hostip)
                    app.isShared = True


        # tile the old section once removed...
        if prevSec and prevSec != self :
            if prevSec.tiled:
                #print "Tiling OLD, ", prevSec, " for app: ", app.getId()
                if prevSec.dynamicMode == 0 :
                    prevSec.tileWindows()
                else :
                    prevSec.tileOnePerDisplay()
            else :
                prevSec.releaseSpace(app)

        # if we are in tile mode, tile instead
        if self.tiled:
            #print "Tiling section: ", self
            if self.dynamicMode == 0 :
                self.tileWindows()
            else :
                self.tileOnePerDisplay()
            return

        # margin for fitting
        margin = 10

        sx = self.getX() + margin
        sy = self.getY() + margin
        sw = self.getWidth() - margin*2
        sh = self.getHeight() - margin*2

        if not cx or not cy:
            cx = app.getCenterX()
            cy = app.getCenterY()

        newA = self.getArea()
        oldA = 1

        # the app is too big so make it smaller
        if app.getWidth() > self.getWidth() or \
               app.getHeight() > self.getHeight():
            app.fitWithin(sx, sy, sw, sh, margin=0, saveBounds=False, cx=cx, cy=cy)


        # the app could be bigger...

        elif False: #newA / float(oldA) > 1.6 and app.getArea() < app.getInitialArea():
            newW = app.getInitialWidth()
            newH = app.getInitialHeight()

            if newW > sw or newH > sh:  # the app is gonna be too big, so make it fit
                app.fitWithin(sx, sy, sw, sh, margin=0, saveBounds=False, cx=cx, cy=cy)

            else:              # just use the original (initial) window size
                if cx + newW/2 > sx+sw:
                    newX = sx+sw - newW
                elif cx - newW/2 < sx:
                    newX = sx
                else:
                    newX = cx - newW/2

                if cy + newH/2 > sy+sh:
                    newY = sy+sh - newH
                elif cy - newH/2 < sy:
                    newY = sy
                else:
                    newY = cy - newH/2

                app.resizeWindow(newX, newX+newW, newY, newY+newH)


        # nothing was fitted so just position the app inside the section
        else:
            newW = app.getWidth()
            newH = app.getHeight()

            if cx + newW/2 > sx+sw:
                newX = sx+sw - newW
            elif cx - newW/2 < sx:
                newX = sx
            else:
                newX = cx - newW/2

            if cy + newH/2 > sy+sh:
                newY = sy+sh - newH
            elif cy - newH/2 < sy:
                newY = sy
            else:
                newY = cy - newH/2

            app.resizeWindow(newX, newX+newW, newY, newY+newH)

    # hyejung
    def expand(self, app):
        # not supported when it is tiling mode
        if self.tiled == True :
            return
        else :
	    app.fixed = True
            # find avilable space around the window, this is not agressive action.
	    self.spaceManager.searchExpandRectangle(app)

    def shove(self, app):
        if self.tiled == True :
            return
        windows = []
        all_windows = self.sageData.getRunningApps().values()
        for w in all_windows:
            if w.section == self:
                windows.append(w)
        self.spaceManager.shove(app, windows)
        del windows

    def shrink(self):
        self.org.closeBtwTile(self)
        self.tightFlag = True

    def gotoNormal(self):
        self.org._updateTiles(self)
        self.tightFlag = False

    # hyejung
    def updateOrder(self, app, x, y):
        self.org.updateOrder(app, x, y, sectionToTile=self)
        if self.tightFlag == True :
            self.org.closeBtwTile(self)

    def moveToLeft(self, app):
        if self.tiled == True :
            self.org.moveToLeft(app, sectionToTile=self)
            if self.tightFlag == True :
                self.org.closeBtwTile(self)
        else :
            windows = []
            all_windows = self.sageData.getRunningApps().values()
            for w in all_windows:
                if w.section == self:
                    windows.append(w)
            app_id = self.spaceManager.getApp(app, windows, LEFT)
            if app_id != None :
                s = None
                for w in all_windows:
                    if w.getId() == app_id:
                        s = w
                        break
                left = app.left
                #bottom = app.bottom

                width = app.getWidth()
                #height = app.getHeight()
                app.fixed = True
                app.left = s.left
                #app.bottom = s.bottom
                app.right = app.left + width
                #app.top = app.bottom + height
                app.resizeWindow(app.left, app.right, app.bottom, app.top)

                #if left < app.right :
                left = app.right +1

                width = s.getWidth()
                #height = s.getHeight()
                s.fixed = True
                s.left = left
                #s.bottom = bottom
                s.right = s.left + width
                #s.top = s.bottom + height
                s.resizeWindow(s.left, s.right, s.bottom, s.top)
                self.createSpace(None)
                app.fixed =False
                s.fixed =False

    def moveToRight(self, app):
        if self.tiled == True :
            self.org.moveToRight(app, sectionToTile=self)
            if self.tightFlag == True :
                self.org.closeBtwTile(self)
        else :
            windows = []
            all_windows = self.sageData.getRunningApps().values()
            for w in all_windows:
                if w.section == self:
                    windows.append(w)
            app_id = self.spaceManager.getApp(app, windows, RIGHT)
            if app_id != None :
                s = None
                for w in all_windows:
                    if w.getId() == app_id:
                        s = w
                        break
                left = s.left
                #bottom = s.bottom

                width = s.getWidth()
                #height = s.getHeight()
                s.fixed = True
                s.left = app.left
                #s.bottom = app.bottom
                s.right = s.left + width
                #s.top = s.bottom + height
                s.resizeWindow(s.left, s.right, s.bottom, s.top)

                #if left < s.right :
                left = s.right +1

                width = app.getWidth()
                #height = app.getHeight()
                app.fixed = True
                app.left = left
                #app.bottom = bottom
                app.right = app.left + width
                #app.top = app.bottom + height
                app.resizeWindow(app.left, app.right, app.bottom, app.top)

                self.createSpace(None)
                app.fixed =False
                s.fixed =False

    def moveToUp(self, app):
        if self.tiled == True :
            self.org.moveToUp(app, sectionToTile=self)
            if self.tightFlag == True :
                self.org.closeBtwTile(self)
        else :
            windows = []
            all_windows = self.sageData.getRunningApps().values()
            for w in all_windows:
                if w.section == self:
                    windows.append(w)
            app_id = self.spaceManager.getApp(app, windows, TOP)
            if app_id != None :
                s = None
                for w in all_windows:
                    if w.getId() == app_id:
                        s = w
                        break
                bottom = s.bottom

                height = s.getHeight()
                s.fixed = True
                s.bottom = app.bottom
                s.top = s.bottom + height
                s.resizeWindow(s.left, s.right, s.bottom, s.top)

                bottom = s.top +1

                height = app.getHeight()
                app.fixed = True
                app.bottom = bottom
                app.top = app.bottom + height
                app.resizeWindow(app.left, app.right, app.bottom, app.top)

                self.createSpace(None)
                app.fixed =False
                s.fixed =False

    def moveToDown(self, app):
        if self.tiled == True :
            self.org.moveToDown(app, sectionToTile=self)
            if self.tightFlag == True :
                self.org.closeBtwTile(self)
        else :
            windows = []
            all_windows = self.sageData.getRunningApps().values()
            for w in all_windows:
                if w.section == self:
                    windows.append(w)
            app_id = self.spaceManager.getApp(app, windows, BOTTOM)
            if app_id != None :
                s = None
                for w in all_windows:
                    if w.getId() == app_id:
                        s = w
                        break
                bottom = app.bottom

                height = app.getHeight()
                app.fixed = True
                app.bottom = s.bottom
                app.top = app.bottom + height
                app.resizeWindow(app.left, app.right, app.bottom, app.top)

                bottom = app.top +1

                height = s.getHeight()
                s.fixed = True
                s.bottom = bottom
                s.top = s.bottom + height
                s.resizeWindow(s.left, s.right, s.bottom, s.top)
                self.createSpace(None)
                app.fixed =False
                s.fixed =False

    def tileWindows(self):
        self.org.tileWindows(sectionToTile=self)
        if self.tightFlag == True :
            self.org.closeBtwTile(self)

    def tileOnePerDisplay(self):
        self.org.tileOnePerDisplay(sectionToTile=self)

    def unTileWindows(self):
        if not self.tiled:
            self.org.unTileWindows(self.getSectionApps(), sectionToTile=self)

    def setTileMode(self, mode):
        self.dynamicMode = mode
        #print mode
        #self.tiled = flag
        self.tightFlag = False
        if mode == 0 :
            self.tiled = True
            self.labelinfo.setLabel("Tile Mode")
            self.labelinfo.updateBackgroundColor(10,50,50)
            self.layoutB.setLabel("Tile-II")
            windows = self.sageData.getRunningApps().values()
            for w in windows:
                if w.section == self:
                    w.backup()
            self.tileWindows()
        elif mode == 1 :
            self.tiled = True
            self.labelinfo.setLabel("Tile Mode-Display")
            self.labelinfo.updateBackgroundColor(10,50,50)
            self.layoutB.setLabel("FREE")
            windows = self.sageData.getRunningApps().values()
            for w in windows:
                if w.section == self:
                    w.backup()
            self.tileOnePerDisplay()
        elif mode == 2 :
            self.tiled = False
            self.labelinfo.setLabel("Free Mode")
            self.labelinfo.updateBackgroundColor(50,50,50)
            self.layoutB.setLabel("DYNAMIC")
            self.spaceManager.clearRectangles()
            windows = self.sageData.getRunningApps().values()
            for w in windows:
                if w.section == self:
                     #w.restore()
                     self.addSpace(w)
        elif mode == 3 :
            self.tiled = False
            self.labelinfo.setLabel("Dynamic Mode")
            self.labelinfo.updateBackgroundColor(50,50,50)
            windows = self.sageData.getRunningApps().values()
            self.spaceManager.clearRectangles()
            for w in windows:
                if w.section == self:
                     #w.restore()
                     self.addSpace(w)
            self.layoutB.setLabel("TILE")

    def getBounds(self):
        return self.bounds

    def getArea(self):
        return self.bounds.getArea()

    def getWidth(self):
        return self.bounds.getWidth()

    def getHeight(self):
        return self.bounds.getHeight()

    def getX(self):
        return self.bounds.left

    def getY(self):
        return self.bounds.bottom

    def _onSplitterMoved(self):
        getLayoutSections().recalculateSections(self)
        writeLog(LOG_SECTION_RESIZE, self, self.bounds)


    def _onMultiTouchSwipe(self, event):
        if event.lifePoint == GESTURE_LIFE_END:
            self.p._resetCurtain()

        else:

            # what is the predominant direction of the gesture??
            """
            if muchGreater(abs(event.dX), abs(event.dY)):   # HORIZONTAL...  collapse a panel
                return
                if abs(event.dX) > self.__minGestureDist: #170*getGlobalScale():
                    self.collapse(True)
                    event.device._resetMultiTouch()
                    self.p._resetCurtain()
                else:
                    #print "Drawing at: ", float(event.dX) / self.__minGestureDist
                    self.p._drawCurtain(HORIZONTAL, float(event.dX) / self.__minGestureDist )
            """
            #else:                                 # VERTICAL....   minimize all apps
            if event.dY < -1*self.__minGestureDist: #-170*getGlobalScale():
                self.__minimizeAllApps()
                event.device._resetMultiTouch()
                self.p._resetCurtain()
            else:
                #print "Drawing at: ", float(abs(event.dY)) / self.__minGestureDist
                self.p._drawCurtain(VERTICAL, float(abs(event.dY)) / self.__minGestureDist )


    def __minimizeAllApps(self):
        writeLog(LOG_SECTION_MINIMIZE_ALL, self)
        for app in self.getSectionApps():
            getLayoutSections().minimizeApp(app)


    # ------------   COLLAPSE SECTION   --------------#


    def __onCollapseBtn(self, btn):
        self.collapse( btn.getState() == BUTTON_DOWN )


    def __findSuitableParent(self, sec=None):
        """ finds the top-most, direct parent of that has
            the splitter of the same direction as ours
        """

        if not sec: sec = self

        if sec.parent and sec.parent.splitter and sec.splitter and \
                sec.parent.splitter.direction == sec.splitter.direction:
            return self.__findSuitableParent(sec.parent)
        else:
            return sec


    def __distributeSpace(self, newSpace):
        parent = self.__findSuitableParent(self.parent)

        spl = parent.splitter
        if parent.relPos == RIGHT or parent.relPos == TOP:
            spl.setPos( spl.getX() - newSpace[0], spl.getY() - newSpace[1] )
        else:
            spl.setPos( spl.getX() + newSpace[0], spl.getY() + newSpace[1] )
        spl._refresh()
        return parent


    def collapse(self, doCollapse):
        if not self.parent: return   # no collapse on root...

        # find parent's splitter
        spl = self.parent.splitter

        if doCollapse:
            spl._preCollapsedPos = spl.relPos  # preserve the old position

            # we simulate collapse of the panel by moving the parent's splitter
            # so find the new position of the splitter that will make the panel look collapsed
            # also, find the right parent to give all the empty space to...
            # if none found, give it to the sibling
            if self.relPos == TOP or self.relPos == RIGHT:
                newSpace = spl.setRelPos( 1-COLLAPSE_RATIO )  # 15% of the section
            else:
                newSpace = spl.setRelPos( COLLAPSE_RATIO )
            self.layoutB.hide()

        else:
            newSpace = spl.setRelPos(spl._preCollapsedPos)
            #newSpace = (-1*newSpace[0], -1*newSpace[1])  # invert the newspace since we are restoring
            self.layoutB.show()

        #resizedParent = self.__distributeSpace( newSpace )

        # this will update everything based on the new splitter position
        spl._refresh()
        #getLayoutSections().recalculateSections( resizedParent )
        getLayoutSections().recalculateSections( self.parent )
        self._collapsed = doCollapse

        #if doCollapse:
        #    self.tileWindows()
        #else:
        #    self.unTileWindows()



    # ------------   EXPORT SECTION   --------------#

    def __onEDLBtn(self, btn):
        print("__onEDLBtn")
        movielist = {}
        for app in self.getSectionApps():
            if not app.isMinimized() and "mplayer" in app.getName().lower():
                appo = getOverlayMgr().getAppOverlay(app)
                print("App: %s" % app.getName())
                print("\t filename %s" % appo.fullpathname)
                print("\t center %d x %d" % ( app.getCenterX(), app.getCenterY() ) )
                print("\t l r t b %d %d %d %d" % ( app.getLeft(), app.getRight(), app.getTop(), app.getBottom() ) )
                movielist[appo.fullpathname] = [app.getCenterX(), app.getCenterY(), app.getLeft(), app.getRight(), app.getTop(), app.getBottom() ]

        if len(movielist) > 0:
            # sorting
            sorted_app = sorted(movielist.iteritems(), key=lambda (k,v): v[0])

            # name of the doc is based on the time
            docName = time.strftime("%a_%b%d_%Y_%X", time.localtime())
            pdir = opj(getFileServer().GetLibraryPath(), "playlist")
            vdir = opj(getFileServer().GetLibraryPath(), "video")
            # the image path saved by this function
            playlist = opj(pdir, "Playlist_"+docName+".m3u")
            fpl = open(playlist, 'w+')
            fpl.write("#EXTM3U\n")
            for im in sorted_app:
                fn = os.path.relpath( opj(vdir, im[0]) , vdir)
                fpl.write("#EXTINF: %s\n" % im[0])
                fpl.write("%s\n" % opj(opj("..","video"),fn) )
            fpl.close()
            showFile(playlist, self.bounds.left+20, self.bounds.bottom+20)
        print("________")

    def __onPDFBtn(self, btn):
        #print("__onPDFBtn")
        imagelist = {}
        for app in self.getSectionApps():
            if not app.isMinimized() and "imageviewer" in app.getName().lower():
                appo = getOverlayMgr().getAppOverlay(app)
                #print("App: %s" % app.getName())
                #print("\t filename %s" % appo.fullpathname)
                #print("\t center %d x %d" % ( app.getCenterX(), app.getCenterY() ) )
                #print("\t l r t b %d %d %d %d" % ( app.getLeft(), app.getRight(), app.getTop(), app.getBottom() ) )
                #imagelist.append( appo.fullpathname )
                imagelist[appo.fullpathname] = [app.getCenterX(), app.getCenterY(), app.getLeft(), app.getRight(), app.getTop(), app.getBottom() ]

        if len(imagelist) > 0:
            # sorting
            sorted_app = sorted(imagelist.iteritems(), key=lambda (k,v): v[0])
            #sorted_two = sorted(sorted_app, key=lambda (k,v): v[1], reverse=True)

            # name of the doc is based on the time
            docName = time.strftime("%a_%b%d_%Y_%X", time.localtime())
            pdir = opj(getFileServer().GetLibraryPath(), "pdf")
            idir = opj(getFileServer().GetLibraryPath(), "image")
            # the image path saved by this function
            storyboard = opj(pdir, "Storyboard_"+docName+".pdf")
            mergeCmd = "convert -density 150 "
            for im in sorted_app:
                fn = opj(idir, im[0])
                mergeCmd += " -gravity None " + fn + " -box white -gravity North -annotate 0 '%f' "
            # in a Letter page
            #mergeCmd += " -gravity None -page Letter -density 72 %s " % storyboard
            mergeCmd += " -gravity None -page 792x612 -density 72 %s " % storyboard
            # full size (first image dictates the page size)
            #mergeCmd += " -gravity None -density 72 %s " % storyboard
            print("Command: ", mergeCmd)
            if hasattr(sp, "check_call"):
                sp.check_call(mergeCmd.split())
            else:
                sp.call(mergeCmd.split())
            showFile(storyboard, self.bounds.left+20, self.bounds.bottom+20)
        print("________")


    # ------------   Send pointer to remote location   --------------#
    def hidePointer(self, deviceName):
        dn = deviceName.split(":")[1]
        if deviceName in self.pointers:
            self.pointers.remove(deviceName)
            if self.manager.conn.connected:
                self.manager.disconnect()

    def forwardPointer(self, deviceName, x, y):
        if self.isShared:
            dn = deviceName.split(":")[1]
            if deviceName not in self.pointers:
                self.pointers.add(deviceName)
                self._sendInitialMsg(dn, 10) # 10 : HAS_DOUBLE_CLICK
                # Get handlers on the remote site
                rgate, rdata = getGate( self.hostip )
                # Get the remote display dimensions
                self.remotedisplay = rdata.getDisplayInfo()
            localw = float ( self.getWidth() )
            localh = float ( self.getHeight() )
            localx = float ( self.getX() )
            localy = float ( self.getY() )
            remotew = float ( self.remotedisplay.sageW )
            remoteh = float ( self.remotedisplay.sageH )
            lx = (x-localx) / localw
            ly = (y-localy) / localh
            offsetx = 0.0
            offsety = 0.0
            # adjust remote dimensions to match local aspect ratio
            if (remotew/remoteh) >= (localw/localh):
                remotew = remoteh * localw / localh
                offsetx = ( float ( self.remotedisplay.sageW ) - remotew ) / 2.0
            else:
                remoteh = remotew * localh / localw
                offsety = ( float ( self.remotedisplay.sageH ) - remoteh ) / 2.0
            lx = lx * remotew
            ly = ly * remoteh
            if offsetx > 0.0:
                lx += offsetx
            if offsety > 0.0:
                ly += offsety
            lx = lx / float( self.remotedisplay.sageW )
            ly = ly / float( self.remotedisplay.sageH )
            self._sendMsg(dn, 1, lx,ly)  # 1 : move

    def _sendMsg(self, dn, *data):
        msg = ""
        for m in data:
            msg+=str(m)+" "
        self.manager.sendMessage(dn+"@"+WALL_NAME, "mouse", msg)

    def _sendInitialMsg(self, dn, *data):
        msg = ""
        for m in data:
            msg+=str(m)+" "
        self.manager.initialMsg(dn+"@"+WALL_NAME, "mouse", msg)

    # ------------   MASTER SECTION   --------------#

    def __onMasterBtnUp(self, btn):
        if self.isShared:
            # section not shared anymore
            self.isShared = False
            # close the pointer connection
            if self.manager.conn.connected:
                self.manager.disconnect()
            self.manager.quit()
            self.pointers.clear()
            self.remotedisplay = None

            # flip the flag on the apps in the section
            local_apps = getSageGate().getAppStatus()
            for app in self.getSectionApps():
                if app.isShared:
                    local_params = local_apps[str(app.appId)][1].split()
                    directory, local_filename = os.path.split( local_params[-1] )
                    for h in app.sharedHosts:
                        rgate, rdata = getGate( h )
                        # Get remote information
                        remote_apps  = rgate.getAppStatus()
                        running_apps = rdata.getRunningApps()
                        winner = None
                        for k in remote_apps:
                            ra = remote_apps[k]
                            rparams = ra[1].split()
                            rdir, rfile = os.path.split( rparams[-1] )
                            if rfile == local_filename:
                                winner = int(k)
                        for v in running_apps.values():
                            remote_filename = v.title
                            if v.appName == app.appName:
                                if v.appId == winner:
                                    rgate.sendAppEvent(APP_QUIT, v.sailID)
                    app.isShared = False
                    app.sharedHosts.clear()


    def __onMasterBtnDown(self, btn):
        setMasterSiteMode(True)
        # Get the host to share with
        site = getMasterSite()
        if site:
            print("Master section: ", site, site )
            self.isShared = True
            self.hostip = site
            # open a device manager connection
            self.manager = ManagerConnection(site)
            # Share content of the section
            gate = getSageGate()
            addGate(site)
            for app in self.getSectionApps():
                if not app.isMinimized() and not app.isShared and ( "imageviewer" in app.getName().lower() or "mplayer" in app.getName().lower() or "pdfviewer" in app.getName().lower() ):
                    #print("App: %s" % app.getName())
                    gate.showContentRemotely(app, site)
                    app.sharedHosts.add(site)
                    app.isShared = True

    # ------------   SPLIT SECTION   --------------#

    def __onSplitBtn(self, btn):
        # make the splitter first
        d = btn.getUserData()   # direction
        if d == HORIZONTAL:
            x = self.bounds.left
            #y = self.bounds.getCenterY()
            y = self.vs_y
        else:
            #x = self.bounds.getCenterX()
            x = self.vs_x
            y = self.bounds.bottom

        self.split(x,y,d)



    def split(self, x, y, direct):
        """ splits the section at x,y in specified direction """

        # figure out where we split the section
        s = int(10*(getGlobalScale()/2.0))  # thickness of the splitter
        if direct == HORIZONTAL:
            x = self.bounds.left
            w = self.bounds.getWidth()
            h = s
        else:
            y = self.bounds.bottom
            h = self.bounds.getHeight()
            w = s
            #sanghwa - splitter shift
            dpWidth = getSageData().getDisplayInfo().sageW
            if x>dpWidth/4-50 and x<=dpWidth/4:
                x = dpWidth/4-50
            if x<dpWidth/4+50 and x>=dpWidth/4:
                x = dpWidth/4+90
            if x>dpWidth/2-50 and x<=dpWidth/2:
                x = dpWidth/2-50
            if x<dpWidth/2+50 and x>=dpWidth/2:
                x = dpWidth/2+90
            if x>dpWidth*0.75-50 and x<=dpWidth*0.75:
                x = dpWidth/4*3-50
            if x<dpWidth*0.75+50 and x>=dpWidth*0.75:
                x = dpWidth/4*3+90


        # make the splitter
        self.splitter = splitterMod.Splitter(direction=direct)
        self.splitter.setUserData(self)
        self.splitter.setPos(x,y)
        self.splitter.setSize(w,h)
        self.addWidget(self.splitter)

        # actually make the two new sections
        self.removeWidgets()
        getLayoutSections()._splitSection(self, self.splitter)


    #GD # ------------   CLEAR SECTION   --------------#
    def __onClearBtn(self, btn):
	apps = self.getSectionApps()
        for app in apps:
	    self.org.sageGate.shutdownApp(app.getId())
        self.spaceManager.clearRectangles()
        self.tileW =0
        self.tileH =0
        self.areaW =0
        self.areaH =0
        self.numCols = 0
        self.numRows = 0
        self.__tiledWindows =[]
        self.appWindows = {}
        self.max_priority = 1

    def __onTestBtn(self, btn):
        analyzer = getAnalyzer()
        type = analyzer.getAction(None)
        if type  == EVT_ANAL_NO_PATTERN:
            return
        elif type  == EVT_ANAL_TO_SESSION :
            newSec = analyzer.getSection()
            if newSec and newSec != self:   # the app is in another section now
                if newSec.tiled == True :
	            apps = self.getSectionApps()
                    for app in apps:
                        newSec.fitAppInSection(app)
                else :
	            apps = self.getSectionApps()
                    for app in apps:
                        app.fixed = False
                        app.section = newSec
                    newSec.createSpace(None)
                if self != newSec :
                    if self.tiled:
                        if self.dynamicMode == 0 :
                            self.tileWindows()
                        else :
                            self.tileOnePerDisplay()
                    else :
                        self.spaceManager.clearRectangles()
        else:
	    apps = self.getSectionApps()
            for app in apps:
		    app.runPrevAction()

    def __onNewBtn(self, btn):
        #if btn.getState() == BUTTON_DOWN:
        # clear all apps
        for app in self.sageData.getRunningApps().values():
	    self.org.sageGate.shutdownApp(app.getId())
	'''for sec in getLayoutSections().dataInSecs :
	    getLayoutSections().removeDataIn(sec)'''
	getLayoutSections().removeAllDataIn()
        getLayoutSections().removeAllSections()
        self.spaceManager.clearRectangles()

    def __onBrowserBtn(self, btn):
         getBrowser().showBrowser(self.vs_x, self.vs_y)

    def __onSetCenterBtn(self, btn):
        getLayoutSections().setCenter(self.vs_x)
        #print "set center", self.vs_x, getLayoutSections().off_center

    def __onDataInBtn(self, btn):
        currentUser = str(btn.getEvtDeviceId())
        if self.userIdx_dataIn == 0 :
                self.dataInUser.insert(0,currentUser)
                self.userIdx_dataIn = self.userIdx_dataIn + 1
                self.setDataIn(USERINPUT_TYPE)
        else :
            self.dataInUser.insert(self.userIdx_dataIn, currentUser)
            self.userIdx_dataIn = self.userIdx_dataIn + 1
            self.setDataIn(USERINPUT_TYPE)
            for i in range(self.userIdx_dataIn-1) :
                if self.dataInUser[i] == currentUser :
                    del self.dataInUser[self.userIdx_dataIn-1]
                    del self.dataInUser[i]
                    self.userIdx_dataIn = self.userIdx_dataIn - 2
		    if self.userIdx_dataIn == 0 :
                        self.setDataIn(NOT_DEFINED_TYPE)
                    getLayoutSections().removeDataIn(self)
                    break
        if self.inType == USERINPUT_TYPE :
            getLayoutSections().updateAllDataIn(self)
            
        '''print "------------current DataIn users list---------------"
        for i in range(self.userIdx_dataIn) :
            print i,"user...",self.dataInUser[i]
        print "---------------------------------------------"'''
        self.userinfo.setLabel(str(self.userIdx_dataIn))

    # UserInfo Popup - added by sanghwa
    def __onUserInfo (self, event) :
        self.userinfoP = sizer.makeNew(direction=VERTICAL)
        self.userinfoP.setTransparency(0)
        self.userinfoP.setPos(event.x+20,event.y-30)
        for user in self.dataInUser :
            self.userinfoP.addChild(label.makeNew(label=str(user), fontSize=NORMAL))
        self.addWidget(self.userinfoP)

    # DataIn Info Popup - added by sanghwa
    def __onDataInInfo (self, event):
        self.dataInInfoP = sizer.makeNew(direction=VERTICAL)
        self.dataInInfoP.setTransparency(0)
        self.dataInInfoP.setPos(event.x+20,event.y-30)
        for user in self.dataInUser :
            self.dataInInfoP.addChild(label.makeNew(label=str(user), fontSize=NORMAL))

        self.addWidget(self.dataInInfoP)

    def setDataIn(self, type):
        #print "data in", self.inType, USERINPUT_TYPE, self
        self.inType = type
        if self.inType == USERINPUT_TYPE:
            self.inputinfo.setLabel("Data In")
            #self.inputinfo.updateBackgroundColor(10,50,50)
            self.inSec = None
            self.outSec = None
        elif self.inType == SECTION_TYPE:
            self.inputinfo.setLabel("Section In")
            self.inputinfo.updateBackgroundColor(50,10,50)
        else : # NOT_DEFINED_TYPE
            self.inputinfo.setLabel("-")
            self.inputinfo.updateBackgroundColor(50,50,50)
            self.inSec = None
            self.outSec = None

    # remove DataIn info - added by sanghwa
    def removeDataInInfo(self, user):
        if user in self.dataInUser :
            self.dataInUser.remove(user)
            getLayoutSections().removeDataIn(self)

    # remove Join info - added by sanghwa
    def removeJoinInfo(self) :
        self.joinON = False
        for user in self.user :
            print "del user...", user
            self.removeDataInInfo(user)
            self.user.remove(user)


class MinimizeSection(Section):
    def __init__(self, bounds):
        Section.__init__(self, bounds, None, None, False, tiled=True)
        self._makePanel()
        self._isMinimizePanel = True

    def _makePanel(self):
        self.p = panel.Panel()
        self.p.setBackgroundColor(10,10,10)
        self.p.setTransparency(50)
        self.p._canScale = False
        self.p._eventTransparent = True
        self.p.fitInWidth(False)
        self.p.fitInHeight(False)
        #self.p.drawBorder(True)
        self._updateSectionBounds()
        self.addWidget(self.p)


class Sections:
    def __init__(self):
        self.addWidget = getOverlayMgr().addWidget
        self.removeWidget = getOverlayMgr().removeWidget
        self.sageData = getSageData()
        self.evtMgr = getEvtMgr()

        #sanghwa
        self.lock = False

        # so that others can access it
        setLayoutSections(self)

        # make the main, root section
        self.disp = self.sageData.getDisplayInfo()
        l = 0
        r = self.disp.sageW
        b = self.disp.usableZeroY
        t = b + self.disp.usableH
        self.root = Section( Bounds(l, r, t, b), None)
        #self.root.setIn(USERINPUT_TYPE)

        # make all the minimize sections...
        self.__minimizeSections = []
        minSectionWidth = int(self.disp.sageW / NUM_MINIMIZE_SECTIONS)  # the width of each section
        for i in range(0, NUM_MINIMIZE_SECTIONS):
            minL = minSectionWidth*i
            minR = minSectionWidth*(i+1)
            self.__minimizeSections.append( MinimizeSection( Bounds(minL, minR, b, 0)) )
        #:self.__makeMinimizePanel()  # just for the borders actually

        #self.__agentPlugins = []
        #self.__loadAllPlugins()

        # hyejung
        self.selectedApp = None
        self.maximizedApp = None
        self.center_x = int(r / 2.0)
        self.off_center = self.center_x
        #self.dataInSec = self.root
        self.dataInSec = None
        self.dataInSecs = []    # sanghwa
        self.dataInIdx = 0    #snaghwa
        self.hasFlow = False

        # event stuff
        self.evtMgr.register(EVT_NEW_APP, self.__onNewApp)
        self.evtMgr.register(EVT_APP_INFO, self.__onAppInfo)
        self.evtMgr.register(EVT_APP_KILLED, self.__onAppKilled)

        # update when remote app is created
        self.evtMgr.register(EVT_NEW_REMOTEAPP, self.__onNewRemoteApp)

        self.deviceId = []

    def setFlow(self):
        self.hasFlow =True

    def goToNext(self):
        print "go to next"
        if self.dataInSec :
            if self.dataInSec.outSec :
                self.dataInSec.transfer(None)
            self.__goToNext()
            #else :
            # find, no in, but outSec


    # has bug...
    def __goToNext(self, sec_list=None):
        if sec_list == None :
            sec_list = self.root
        for child in sec_list.children:
            if child.inSec :
                if child.tiled == True :
                    if child.dynamicMode == 0 :
                        child.tileWindows()
                    else :
                        child.tileOnePerDisplay()
                else :
                    child.createSpace(None)
            self.__goToNext(child)

    def setCenter(self, x):
        #self.off_center = x - self.center_x
        self.off_center = x
        self.__reSorted()

    def __reSorted(self, sec_list=None):
        if sec_list == None :
            sec_list = self.root
        for child in sec_list.children:
            self.__reSorted(child)
            if child.tiled == False :
                child.createSpace(None)



    def adjustCenter(self, app):
        #for maximize case
        off = self.off_center - self.center_x
        if off == 0 : return

	left = app.left + off
        right = app.right + off
        if left < 0 :
            left = 0
            right = app.right - app.left
        elif right > self.disp.sageW :
            right = self.disp.sageW
            left = right - (app.right - app.left)
        app.resizeWindow(left, right, app.bottom, app.top)

    def updateAllDataIn(self, sec):
        #self.dataInSec = sec
        if self.dataInSecs.count(sec) < 1 :
            #print "add dataInSec"
            self.dataInSecs.append(sec)
        self.hasFlow =False
        #self.__setAllDataIn(sec, NOT_DEFINED_TYPE)
        self.__setDataIn(sec, USERINPUT_TYPE)

    # removeDataIn section - added by sanghwa
    def removeDataIn(self, sec) :
        if sec in self.dataInSecs :
            self.dataInSecs.remove(sec)
    def removeAllDataIn(self) :
        del self.dataInSecs[0:]

    # Data In more - added by sanghwa
    def __setDataIn(self, sec, type) :
        sec.setDataIn(type)
	sec.inputinfo.updateBackgroundColor(200,0,0)

    def __setAllDataIn(self, sec, type, sec_list=None):
        # now check the rest of the sections
        if not sec_list:
            sec_list=self.root

        for child in sec_list.children:
            if sec != child :
                child.setDataIn(type)
            self.__setAllDataIn(sec, type, child)

    def updateInSec(self):
        self.dataInSec = self.getSectionBySmallist()
        self.dataInSec.setDataIn(USERINPUT_TYPE)
        #print "update in sec - after remove"

    def setMaximized(self, app):
        if self.maximizedApp == None :
            self.maximizedApp = app

    def isFocused(self):
        return self.maximizedApp

    def unFocused(self):
        if self.maximizedApp :
            apps = []
            apps.append(self.maximizedApp)
            getLayoutOrganization().restoreFromMaximize(apps)
            #self.maximizedApp.unfocusWindow()
            self.maximizedApp.maximized = False
            writeLog(LOG_WINDOW_RESTORE, self.maximizedApp.getId(), self.maximizedApp.getBounds())
            self.maximizedApp = None
            return True
        return False

    def __makeMinimizePanel(self):
        p = panel.Panel()
        p.setPos(0,0)
        p.setSize(self.disp.sageW, self.disp.usableZeroY)
        p.setBackgroundColor(0,0,0)
        p.setTransparency(50)
        p._canScale = False
        p._eventTransparent = True
        p.fitInWidth(False)
        p.fitInHeight(False)
        p.drawBorder(True)
        self.addWidget(p)


    def getApp(self):
        return self.selectedApp

    def setApp(self, app):
        self.selectedApp = app

        # If a new remote app appears, just relayout
    def __onNewRemoteApp(self, event):
        self.recalculateSections(self.root)

    # data upload listner - added by sanghwa
    def onUploadMessage(self, deviceId):
        self.deviceId.append(str(deviceId))
        #print "onUploadMessage deviceId ... ",len(self.deviceId)-1,deviceId

    def __onNewApp(self, event):
        app = event.app
        #newSec = self.dataInSec
        newSec = None
        # set dataInSecs - added by sanghwa
        for sec in self.dataInSecs :
            if self.deviceId[self.dataInIdx] in sec.dataInUser :
                #print "onNewApp!!! deviceId...",self.dataInIdx," : ",self.deviceId[self.dataInIdx]
                newSec = sec
                #break
        self.dataInIdx = self.dataInIdx+1
        #newSec = self.getSectionByApp(app)
        #myung ji: placing in smallist section
        """if self.dataInSec != None :
            newSec = self.dataInSec
        else :
            print "new- --- and run"
            newSec = self.getSectionBySmallist()
            newSec.setDataIn(1900)
            self.dataInSec = newSec"""

        #print newSec.tiled
        # hyejung - priority testing...
        if newSec != None :
            #print "load success!!!"
            current_time =  time.time()
            diff = current_time - newSec.loaded_time
            #print diff, current_time, newSec.loaded_time
            newSec.loaded_time =current_time
            if diff > 30 :
                newSec.max_priority += 1
            app.setPriority(newSec.max_priority)

            if newSec.tiled == True :
                newSec.fitAppInSection(app)
            else :
                newSec.createSpace(app)
        else :
            sageGate.shutdownApp(app.getId())


    def __onAppInfo(self, event):
        """ this is needed in case some other UI client moves the app...
            otherwise, the appOverlay actually does this
        """
        #if event.myMsg:  # this message came from us so don't do anything! (otherwise race conditions could happen)
        #    return
        if not event.app.maximized and not event.app.sectionMaximized:
            newSec = self.getSectionByApp(event.app)
            newSec.updateSpace(event.app)
            if event.app.section._isMinimizePanel:
                if event.app.section != newSec:  # did the app actually change a section?
                    newSec.fitAppInSection(event.app)

    def __onAppKilled(self, event):
        newSec = self.getSectionByApp(event.app)
        if newSec.tiled == True :
            event.app.section = None
            if newSec.dynamicMode == 0:
                newSec.tileWindows()
            else :
                newSec.tileOnePerDisplay()
        else :
            newSec.releaseSpace(event.app)
        #event.app.releaseAgent()

    def recalculateSections(self, section):
        """
            recursively adjust the sizes and positions of all children of "section"
            - typically called after a splitter moves or a section is collapsed
        """

	# Root section
	"""if not section.parent:
                # resize and reposition the apps
                for app in section.getSectionApps():
                    if not app.isMinimized():
                        section.fitAppInSection(app)
		return"""

        # first figure out where the splitter is
        sp = section.splitter
        sDir = sp.direction
        if sp and sDir == HORIZONTAL:
            sPos = sp.getY()
        else:
            sPos = sp.getX()


        if section._collapsed: return


        # adjust the two children based on the splitter
        for child in section.children:

            if sDir == HORIZONTAL:   # HORIZONTAL
                if child.relPos == TOP:
                    child.bounds.bottom = sPos
                    child.bounds.top = section.bounds.top
                else:
                    child.bounds.top = sPos
                    child.bounds.bottom = section.bounds.bottom
                child.bounds.left = sp.getBounds().left
                child.bounds.right = sp.getBounds().right

            else:                    # VERTICAL
                if child.relPos == LEFT:
                    child.bounds.right = sPos
                    child.bounds.left = section.bounds.left
                else:
                    child.bounds.left = sPos
                    child.bounds.right = section.bounds.right
                child.bounds.top = sp.getBounds().top
                child.bounds.bottom = sp.getBounds().bottom

            child._updateSectionBounds()
            child._updateSplitter()


            if len(child.children) > 0:
                self.recalculateSections(child)
            else:
                # resize and reposition the apps since the sections resized
                for app in child.getSectionApps():
                    if not app.isMinimized():
                        child.fitAppInSection(app)


    def _splitSection(self, section, splitter):
        """
            actually makes the two new sections based on the passed in splitter
        """

        bounds = section.bounds

        if splitter.direction == HORIZONTAL:
            sPos = splitter.getY()

            # calculate the bounds for the new sections
            # bottom
            r = bounds.right
            t = sPos
            l = bounds.left
            b = bounds.bottom
            section1 = Section( Bounds(l, r, t, b), section, BOTTOM )

            # top
            t = bounds.top
            b = sPos
            section2 = None
            if section.inType == USERINPUT_TYPE :
                section2 = Section( Bounds(l, r, t, b), section, TOP, tiled=section.tiled, type=USERINPUT_TYPE)
                #self.dataInSec = section2
                self.updateAllDataIn(section2)
                section2.dataInUser.extend(section.dataInUser)
                section2.userIdx_dataIn = len(section.dataInUser)
                section2.userinfo.setLabel(str(len(section.dataInUser)))
                #section2.setOut(section.outSec)
                section2.dynamicMode =  section.dynamicMode
            else :
                section2 = Section( Bounds(l, r, t, b), section, TOP, tiled=section.tiled, type=section.inType)
                section2.setOut(section.outSec)
                if section.inSec :
                    section.inSec.setOut(section2)
                    section.inSec = None
                    section.inType = NOT_DEFINED_TYPE
                section2.dynamicMode =  section.dynamicMode
            section2.setTileMode(section.dynamicMode)

            windows = self.sageData.getRunningApps().values()
            if section.tiled == True :
                for w in windows:
                   if w.section == section:
                       section2.fitAppInSection(w)
            else :
                if section.dynamicMode == 3 :
                    for w in windows:
                       if w.section == section:
                           w.section = section2
                    # it will be updated... hyejung
                    section2.createSpace(None)
                elif section.dynamicMode == 2 :
                    for w in windows:
                        section2.createSpace(w)
        else:
            sPos = splitter.getX()

            # calculate the bounds for the new sections
            # left
            r = sPos
            t = bounds.top
            l = bounds.left
            b = bounds.bottom
            section1 = None
            if section.inType == USERINPUT_TYPE :
                section1 = Section( Bounds(l, r, t, b), section, LEFT, tiled=section.tiled, type=USERINPUT_TYPE)
                #self.dataInSec = section1
                self.updateAllDataIn(section1)
                section1.dataInUser.extend(section.dataInUser)
                section1.userIdx_dataIn = len(section.dataInUser)
                section1.userinfo.setLabel(str(len(section.dataInUser)))
                #section1.setOut(section.outSec)
                section1.dynamicMode =  section.dynamicMode
            else :
                section1 = Section( Bounds(l, r, t, b), section, LEFT, tiled=section.tiled, type=section.inType )
                section1.setOut(section.outSec)
                if section.inSec :
                    section.inSec.setOut(section1)
                    section.inSec = None
                    section.inType = NOT_DEFINED_TYPE
                section1.dynamicMode =  section.dynamicMode
            section1.setTileMode(section.dynamicMode)

            # right
            l = sPos
            r = bounds.right
            section2 = Section( Bounds(l, r, t, b), section, RIGHT )

            windows = self.sageData.getRunningApps().values()
            if section.tiled == True :
                 for w in windows:
                     if w.section == section:
                         section1.fitAppInSection(w)
            else :
                if section.dynamicMode == 3 :
                    for w in windows:
                        if w.section == section:
                            w.section = section1
                    section1.createSpace(None)
                elif section.dynamicMode == 2 :
                    for w in windows:
                        section1.createSpace(w)
                
        section.tiled = False
        section.children = [section1, section2]


        # update app section memberships now
        maximizedApps = []
        for app in section.getSectionApps():

            # maximized apps should be brought to front... so save them here
            if app.maximized or app.sectionMaximized:
                maximizedApps.append(app)

            # if they arent minimized either, reassign their section membership
            elif not app.isMinimized():
                newSec = self.getSectionByApp(app, section)  # are we in section1 or section2 now?
                newSec.fitAppInSection(app)

        # bring the maximized apps to front
        for app in maximizedApps:
            app.bringToFront()



    def getSectionByApp(self, app, sec=None):

        # check the minimize sections first
        #for minSection in self.__minimizeSections:
        #    if minSection.isIn(app.getCenterX(), app.getCenterY()):
        #        return minSection

        # now check the rest of the sections
        if not sec:
            sec=self.root

        for child in sec.children:
            if child.isIn(app.getCenterX(), app.getCenterY()):
                return self.getSectionByApp(app, child)
        return sec


    def getSectionByXY(self, x, y, sec=None):

        # check the minimize sections first
        #for minSection in self.__minimizeSections:
        #    if minSection.isIn(x, y):
        #        return minSection

        # now check the rest of the sections
        if not sec:
            sec=self.root

        for child in sec.children:
            if child.isIn(x,y):
                return self.getSectionByXY(x, y, child)
        return sec

    # hyejung
    def getSection(self, btn, sec):
        retSec = None

        if btn == BTN_LEFT :
           #print "left: ", sec.bounds.left
           if sec.bounds.left > 0 :
               x = sec.bounds.left -2
               y = sec.bounds.bottom + int(sec.bounds.getHeight() / 2.0)
               #print "do sometithing(left) ", x, y
               retSec = self.getSectionByXY(x, y)
        elif btn == BTN_RIGHT :
           #print "right: ", sec.bounds.right
           if sec.bounds.right < self.root.bounds.right :
               x = sec.bounds.right +2
               y = sec.bounds.bottom + int(sec.bounds.getHeight() / 2.0)
               #print "do sometithing(right) ", x, y
               retSec = self.getSectionByXY(x, y)
        elif btn == BTN_UP :
           #print "top: ", sec.bounds.top
           if sec.bounds.top < self.root.bounds.top :
               x = sec.bounds.left + int(sec.bounds.getWidth() / 2.0)
               y = sec.bounds.top + 2
               #print "do sometithing(up) ", x, y
               retSec = self.getSectionByXY(x, y)
        elif btn == BTN_DOWN :
           #print "bottom: ", sec.bounds.bottom
           if sec.bounds.bottom > self.root.bounds.bottom :
               x = sec.bounds.left + int(sec.bounds.getWidth() / 2.0)
               y = sec.bounds.bottom - 2
               #print "do sometithing(down) ", x, y
               retSec = self.getSectionByXY(x, y)
        return retSec


    #myung ji: placing app in smallist section
    def getSectionBySmallist(self, sec=None):
        sections = self.__getLeafSections()
        smallist = sections[0]
        for sec in sections[1:]:
            if(smallist.getWidth()*smallist.getHeight() > sec.getWidth()*sec.getHeight()):
                smallist = sec
        #print "smallist section: ", smallist
        #if not smallist.tiled:
        #    smallist.tiled=True
        #    smallist.tileWindows()
        return smallist


    # myung ji: get all sections
    def __getLeafSections(self):
        leafs=[]
        self.__collectLeafSections(self.root, leafs)
        return leafs


    # myung ji: called by __getLeafSections()
    def __collectLeafSections(self, sec, leafs):
        if not sec:
            sec = self.root
        if len(sec.children)==0:
            leafs.append(sec)
        for child in sec.children:
            self.__collectLeafSections(child, leafs)


    def minimizeApp(self, app):
        """ find minimize section that's closest to the app and minimize the app there """
        minSection = self.getSectionByXY(app.getCenterX(), 5)  # 5 as if the app was down there already...
        minSection.fitAppInSection(app)


         # returns a new section if app is now in a different section or false otherwise
    def isAppInNewSection(self, app, x, y):
        newSec = self.getSectionByXY(x, y)
        if app.section != newSec:
            #print "different session"
            return newSec
        else:
            #print "same session"
            # one more check.
            return None

    def __updateAppSection(self, app):
        app.section = self.getSectionByApp(app)
        return app.section


    def __removeChildren(self, parent, first=True, removingAll=False):
        for child in parent.children:
            self.__removeChildren(child, False, removingAll)
            child.removeWidgets()
            del child

       	parent.children = []
       	self.removeWidget(parent.splitter)
       	parent.splitter = None

    def removeSection(self, section):
        if section == self.root: return

        otherSec = None
        for child in section.parent.children:
            # remove DataIn sections - added by sanghwa
            if child in self.dataInSecs :
                self.dataInSecs.remove(child)
        for child in section.parent.children:
            if section != child :
                otherSec = child
                break
        if otherSec == None :
            return

        assignedSec = section.parent
        if len(otherSec.children) == 0 :
            assignedSec.dynamicMode = otherSec.dynamicMode
            assignedSec.tiled = otherSec.tiled
            self.__removeChildren(assignedSec)
            # make parent's widgets now...
            assignedSec.makeWidgets()
        else :
            self.__removeChildren(section)
            section.removeWidgets()

            # transfer childrent of  otherSec to section.parent
            section1 = otherSec.children[0]
            section2 = otherSec.children[1]
            assignedSec.children = [section1, section2]
            self.removeWidget(assignedSec.splitter)
            assignedSec.splitter = None

            # update bound
            bounds = otherSec.bounds
            new_bounds = assignedSec.bounds
            if section.relPos == BOTTOM or section.relPos == TOP :
                if section1.relPos == LEFT or section1.relPos == RIGHT :
                    w = new_bounds.getHeight()
                    if section.relPos == BOTTOM :
                        section1.bounds.setY(new_bounds.getY())
                        section2.bounds.setY(new_bounds.getY())
                        section1.bounds.setHeight(w)
                        section2.bounds.setHeight(w)
                    else :
                        section1.bounds.setHeight(w)
                        section2.bounds.setHeight(w)
                else :
                    h1 = int((1.0 * section1.bounds.getHeight() / bounds.getHeight()) * new_bounds.getHeight())
                    h2 = int((1.0 * section2.bounds.getHeight() / bounds.getHeight()) * new_bounds.getHeight())
                    if section.relPos == BOTTOM :
                        section1.bounds.setY(new_bounds.getY())
                        section1.bounds.setHeight(h1)
                        section2.bounds.setY(section1.bounds.top)
                        section2.bounds.setHeight(h2)
                    else :
                        section1.bounds.setHeight(h1)
                        section2.bounds.setY(section1.bounds.top)
                        section2.bounds.setHeight(h2)
            else :
                if section1.relPos == BOTTOM or section1.relPos == TOP :
                    w = new_bounds.getWidth()
                    if section.relPos == LEFT :
                        section1.bounds.setX(new_bounds.getX())
                        section2.bounds.setX(new_bounds.getX())
                        section1.bounds.setWidth(w)
                        section2.bounds.setWidth(w)
                    else :  # right
                        section1.bounds.setWidth(w)
                        section2.bounds.setWidth(w)
                else :
                    w1 = int((1.0 * section1.bounds.getWidth() / bounds.getWidth()) * new_bounds.getWidth())
                    w2 = int((1.0 * section2.bounds.getWidth() / bounds.getWidth()) * new_bounds.getWidth())
                    if section.relPos == LEFT :
                        section1.bounds.setX(new_bounds.getX())
                        section1.bounds.setWidth(w1)
                        section2.bounds.setX(section1.bounds.right)
                        section2.bounds.setWidth(w2)
                    else :  # right
                        section1.bounds.setWidth(w1)
                        section2.bounds.setX(section1.bounds.right)
                        section2.bounds.setWidth(w2)

            section1.parent = assignedSec
            section1._updateSectionBounds()
            section1._updateSplitter()
            if len(section1.children) > 0:
                self.recalculateSections(section1)

            section2.parent = assignedSec
            section2._updateSectionBounds()
            section2._updateSplitter()
            if len(section2.children) > 0:
                self.recalculateSections(section2)

            direct = HORIZONTAL
            s = int(10*(getGlobalScale()/2.0))  # thickness of the splitter
            if section1.relPos == LEFT or section1.relPos == RIGHT :
                direct = VERTICAL
                w = s
                h = assignedSec.bounds.getHeight()
                if section2.relPos == RIGHT :
                    x = section2.bounds.left
                else :
                    x = section2.bounds.right
                y = assignedSec.bounds.bottom
            else :
                w = assignedSec.bounds.getWidth()
                h = s
                x = assignedSec.bounds.left
                if section1.relPos == BOTTOM :
                    y = section1.bounds.top
                else :
                    y = section1.bounds.bottom
            assignedSec.splitter = splitterMod.Splitter(direction=direct)
            assignedSec.splitter.setUserData(assignedSec)
            assignedSec.splitter.setPos(x,y)
            assignedSec.splitter.setSize(w,h)
            assignedSec.addWidget(assignedSec.splitter)

            # delete otherSec, other Sec just has splitter widget.
            self.removeWidget(otherSec.splitter)
            otherSec.splitter = None
            del otherSec

            assignedSec = section1

        # change the sections of all apps to the parent of the deleted section
        windows = self.sageData.getRunningApps().values()
        for app in windows :
            self.__updateAppSection(app)

        if assignedSec.tiled == True :
            if assignedSec.dynamicMode == 0 :
                assignedSec.tileWindows()
            else :
                assignedSec.tileOnePerDisplay()
        else:
            assignedSec.spaceManager.clearRectangles()
            for w in windows:
                if w.section == assignedSec:
                    assignedSec.createSpace(w)

    def removeAllSections(self):
        self.__removeChildren(self.root, removingAll=True)
        del self.root
        # make the main, root section
        self.disp = self.sageData.getDisplayInfo()
        l = 0
        r = self.disp.sageW
        b = self.disp.usableZeroY
        t = b + self.disp.usableH
        self.root = Section( Bounds(l, r, t, b), None, type=NOT_DEFINED_TYPE )
        #self.root.setIn(USERINPUT_TYPE)
        self.selectedApp = None
        self.maximizedApp = None
        self.dataInSec = self.root
        self.hasFlow = False


    def __removeAllSections(self):
        # all except the root... but remove root's widgets
        self.__removeChildren(self.root, removingAll=True)
        self.root.removeWidgets()
        self.root._clear()


        # returns the state of all the sections for saving
    def getState(self):
        return self.root


    def loadState(self, root):
        if not root:  # in case we are loading an older state where sections werent saved
            return

        # clear the current state first
        self.__removeAllSections()

        self.__recreateTree(root)

        # update app memberships now
        for app in self.sageData.getRunningApps().values():
            if not app.isMinimized():
                app.section = self.getSectionByApp(app)



    def __recreateTree(self, sec, parent=None):

        # make the splitter if necessary
        newSpl = sec.splitter
        splitter = None
        if newSpl:
            splitter = splitterMod.Splitter(direction=newSpl.direction)
            splitter.setSize(newSpl.size[0], newSpl.size[1])
            splitter.setPos(newSpl.pos[0], newSpl.pos[1])
            splitter.relPos = newSpl.relPos
            if hasattr(newSpl, "_preCollapsedPos"):
                splitter._preCollapsedPos = newSpl._preCollapsedPos


        # make the sections... the first one is root so we
        # use the default one created by Sections class
        if not parent:
            oldSpl = self.root.splitter
            section = self.root
            self.root.tiled = sec.tiled
            if sec.tiled:
                self.root.layoutB.setState(BUTTON_DOWN)
            self.root.splitter = splitter

            if not splitter:  # if it didn't have a splitter, we'll have to re-create the widgets
                self.root.makeWidgets()

        # all other sections beside root
        else:
            section = Section( sec.bounds, parent, relPos=sec.relPos, makeWidgets=(splitter==None), tiled=sec.tiled)
            section.splitter = splitter
            if hasattr(sec, "_collapsed"):
                section._collapsed = sec._collapsed
                section._setButtonCollapsed()


        # assign the section to splitter after it has been created
        if splitter:
            splitter.setUserData(section)
            self.addWidget(splitter)

        # make the children recursively... if any
        for child in sec.children:
            section.children.append(self.__recreateTree(child, section))

        return section


    #sanghwa
    def splitByLine(self, x, y, direct):
        sec = self.findSection(self.root, x, y)
        sec.split(x,y,direct)

    def findSection(self, aSection, x, y):
        if len(aSection.children) == 0:
            if aSection.isIn(x,y) == True:
                return aSection
        else:
            for child in aSection.children:
                sec = self.findSection(child,x,y)
                if sec!= None:
                    return sec
        return None


